package p2p.model.vo
{
	import flash.media.Camera;
	import flash.media.Microphone;
	import flash.net.GroupSpecifier;
	import flash.net.NetConnection;
	import flash.net.NetGroup;
	import flash.net.NetStream;

	[Bindable]
	public class CallerVO
	{
		public var selfKey		 :String;
		public var selfName		 :String = "Unknown";
		public var selfGroupId	 :String = "myGroup/default";
		public var selfGroupName :String;
		
		//array of ClientVO
		public var clients:Array = [];
		
		//array of sent P2PSharedObject classes
		public var sentSO:Array = [];
		//array of received P2PSharedObject classes
		public var receivedSO:Array = [];
		
		public var outStream	 :NetStream;
		public var connection	 :NetConnection;
		public var netGroup		 :NetGroup;
		public var groupSpecifier:GroupSpecifier;
		
		/**
		 * Constructor
		 */
		public function CallerVO()
		{
			connection = new NetConnection();
		}
				
		public function setUpGroup() : void
		{
			groupSpecifier = new GroupSpecifier(selfGroupId);
			groupSpecifier.serverChannelEnabled = true;
			groupSpecifier.multicastEnabled = true;
			groupSpecifier.postingEnabled = true;
			groupSpecifier.routingEnabled = true;
			groupSpecifier.objectReplicationEnabled = true;
			
			netGroup = new NetGroup(connection, groupSpecifier.groupspecWithAuthorizations());
		}
		
		public function setUpStream() : void
		{
			outStream = new NetStream(connection, groupSpecifier.groupspecWithAuthorizations());
		}
		
		public function publish(cam:Camera, mic:Microphone) : void
		{
			outStream.attachCamera(cam);
			mic.setSilenceLevel(0, 1000);
			outStream.attachAudio(mic);
			outStream.publish(selfKey);
		}
		
		public function addClient(sessionKey:String) : ClientVO
		{
			var client:ClientVO = new ClientVO();
			client.sessionKey = sessionKey;
			client.inStream = new NetStream(connection, groupSpecifier.groupspecWithAuthorizations());
			client.play();
			clients.push(client);
			return client;
		}
		
		public function removeClient(sessionKey:String) : void
		{
			for ( var i:int = 0; i <= clients.length; i++ )
			{
				var client:ClientVO = clients[i] as ClientVO;
				if(client.sessionKey == sessionKey)
				{
					clients.splice(i, 1);
					return;
				}
			}
		}
		
		public function setClientNameBySessionKey(name:String, sessionKey:String) : void
		{
			for each (var client:ClientVO in clients)
			{
				if (client.sessionKey == sessionKey)
				{
					client.name = name;
					break;
				}
			}
		}
		
		public function getClientNameBySessionKey(sessionKey:String) : String
		{
			var result:String;
			for each (var client:ClientVO in clients)
			{
				if (client.sessionKey == sessionKey)
				{
					result = client.name;
					break;
				}
			}
			return result;
		}
		
		public function getDestinationBySessionKey(sessionKey:String) : String
		{
			return netGroup.convertPeerIDToGroupAddress(sessionKey);
		}
		
		public function sendPrivateMessage(message:MessageVO) : void
		{
			var destination:String = getDestinationBySessionKey(message.recipientSessionKey);
			netGroup.sendToNearest(message, destination);
		}
		
		public function sendGroupMessage(message:MessageVO) : void
		{
			netGroup.post(message);
		}
		
		public function sendYourName2Group() : void
		{
			var msg:MessageVO = new MessageVO(selfName, null, null, selfKey);
			msg.nameNotification = true;
			netGroup.post(msg);
		}
		
		public function getSentSOByChunkIndex(idx:int) : P2PSharedVO
		{
			return getSOByChunkIndex(idx, sentSO);
		}
		
		public function getReceivedSOByChunkIndex(idx:int) : P2PSharedVO
		{
			return getSOByChunkIndex(idx, receivedSO);
		}
		
		private function getSOByChunkIndex(idx:int, arr:Array) : P2PSharedVO
		{
			var result:P2PSharedVO;
			for each (var so:P2PSharedVO in arr)
			{
				if (idx >= so.descriptor.startChunkIndex && 
					idx <= so.descriptor.endChunkIndex)
				{
					result = so;
					break;
				}
			}
			return result;
		}
	}
}